home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Various / DevDisk 65 (1989)(DevWare PD).zip / DevDisk 65 (1989)(DevWare PD).adf / prosuite / color.c < prev    next >
C/C++ Source or Header  |  1990-07-11  |  19KB  |  719 lines

  1.  
  2. /* *** color.c *************************************************************
  3.  *
  4.  * ColorWindow Routine  --  Color Window Routines
  5.  *     from Book 1 of the Amiga Programmers' Suite by RJ Mical
  6.  *
  7.  * Copyright (C) 1986, 1987, Robert J. Mical
  8.  * All Rights Reserved.
  9.  *
  10.  * Created for Amiga developers.
  11.  * Any or all of this code can be used in any program as long as this
  12.  * entire copyright notice is retained, ok?  Thanks.
  13.  *
  14.  * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
  15.  * All copyright notices and all file headers must be retained intact.
  16.  * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the 
  17.  * resultant object code may be included in any software product.  However, no 
  18.  * portion of the source listings or documentation of the Amiga Programmer's 
  19.  * Suite Book 1 may be distributed or sold for profit or in a for-profit 
  20.  * product without the written authorization of the author, RJ Mical.
  21.  * 
  22.  * HISTORY      NAME            DESCRIPTION
  23.  * -----------  --------------  --------------------------------------------
  24.  * 20 Oct 87    - RJ            Make the window draggable
  25.  * 3 Jan 87     RJ >:-{)*       Clean-up for release      
  26.  * 27 Feb 86    =RJ Mical=      Modified these routines for Zaphod
  27.  * January 86   =RJ=            Modified the originals for Mandelbrot
  28.  * Late 85      =RJ=            Created the color window for Graphicraft
  29.  *
  30.  * *********************************************************************** */
  31.  
  32.  
  33. #include "color.h"
  34.  
  35.  
  36.  
  37. extern struct Gadget ColorTemplateGadgets[COLOR_GADGETS_COUNT];
  38. extern struct Image ColorPropsImages[3];
  39. extern struct PropInfo ColorPropsInfos[3];
  40. extern struct Image ColorRGBImage;
  41. extern struct Image ColorHSLImage;
  42. extern struct Image SuperColorImages[32];
  43. extern USHORT RGBData[];
  44. extern USHORT HSLData[];
  45.  
  46. UBYTE *AllocRemember();
  47. struct IntuiMessage *GetMsg();
  48. struct Window *OpenWindow();
  49.  
  50.  
  51.  
  52. /* ColorMode definitions */
  53. #define COPYCOLOR    1
  54. #define RANGE_FIRST  2
  55. #define RANGE_SECOND 3
  56.  
  57. /* These are the dimensions of the color hit box */
  58. #define COLOR_COLOR_ROWS    (4 * 10)
  59. #define COLOR_COLOR_COLS    (8 * 15)
  60. #define COLOR_COLOR_RIGHT   (COLOR_BOX_LEFT + COLOR_COLOR_COLS - 1)
  61. #define COLOR_COLOR_BOTTOM  (COLOR_COLOR_TOP + COLOR_COLOR_ROWS - 1)
  62.  
  63. VOID ResetColorProps();
  64.  
  65.  
  66. struct NewWindow ColorNewWindow =
  67.     {
  68.     /*        SHORT LeftEdge, TopEdge;        /* screen dimensions of window */
  69.     /*        SHORT Width, Height;                /* screen dimensions of window */
  70.     20, 12,
  71.     COLORWINDOW_WIDTH, COLORWINDOW_HEIGHT,
  72.  
  73.     /*        UBYTE DetailPen, BlockPen;        /* for bar/border/gadget rendering */
  74.     -1, -1,
  75.  
  76.     /*        ULONG IDCMPFlags;                /* User-selected IDCMP flags */
  77.     GADGETDOWN | GADGETUP | MOUSEBUTTONS  
  78.             | MENUPICK | MOUSEMOVE | ACTIVEWINDOW | INACTIVEWINDOW,
  79.  
  80.     /*        ULONG Flags;                        /* see Window struct for defines */
  81.     WINDOWDRAG | SMART_REFRESH | NOCAREREFRESH | ACTIVATE,
  82.  
  83.     /*        struct Gadget *FirstGadget;*/
  84.     &ColorTemplateGadgets[COLOR_GADGETS_COUNT - 1],
  85.  
  86.     /*        struct Image *CheckMark;*/
  87.     NULL,
  88.  
  89.     /*        UBYTE *Title;                          /* the title text for this window */
  90.     (UBYTE *)"Change Colors",
  91.     
  92.     /*        struct Screen *Screen;*/
  93.     NULL,
  94.     
  95.     /*        struct BitMap *BitMap;*/
  96.     NULL,
  97.  
  98.     /*        SHORT MinWidth, MinHeight;         /* minimums */
  99.     0, 0,
  100.     /*        SHORT MaxWidth, MaxHeight;         /* maximums */
  101.     0, 0,
  102.  
  103.     /*        USHORT Type;*/
  104.     CUSTOMSCREEN,
  105. };
  106.  
  107. USHORT ColorMode;
  108. USHORT RangeFirst;
  109. struct Window *ColorWindow = NULL;
  110. struct RastPort *ColorRPort;
  111. struct ViewPort *ColorVPort;
  112. SHORT RowCount, RowHeight, ColumnCount, ColumnWidth;
  113. USHORT SavePalette[32];
  114.  
  115.  
  116.  
  117.  
  118. /* ======================================================================= */
  119. /* === These Routines Open, Render, and Close the Color Window =========== */
  120. /* ======================================================================= */
  121.  
  122. VOID InitColorSizes(depth)
  123. SHORT depth;
  124. /* This routine adjusts the row and column variables based on the number
  125.  * of colors supported by the ColorWindow's screen.
  126.  */
  127. {
  128.     RowCount = 1 << (depth >> 1);
  129.     RowHeight = COLOR_COLOR_ROWS / RowCount;
  130.  
  131.     ColumnCount = 1 << ((depth + 1) >> 1);
  132.     ColumnWidth = COLOR_COLOR_COLS / ColumnCount;
  133. }
  134.  
  135.  
  136.  
  137. VOID DrawBox(rp, left, top, right, bottom)
  138. struct RastPort *rp;
  139. SHORT left, top, right, bottom;
  140. /* A quick utility routine */
  141. {
  142.     SHORT savepen;
  143.  
  144.     savepen = ColorRPort->FgPen;
  145.  
  146.     SetAPen(rp, 1);
  147.     SetDrMd(rp, JAM2);
  148.  
  149.     Move(rp, left, top);
  150.     Draw(rp, left, bottom);
  151.     Draw(rp, right, bottom);
  152.     Draw(rp, right, top);
  153.     Draw(rp, left, top);
  154.  
  155.     SetAPen(ColorRPort, savepen);
  156. }
  157.  
  158.  
  159.      
  160. VOID ColorRectFill(pen)
  161. SHORT pen;
  162. /* This routine sets the pen in the RastPort as the current pen selected
  163.  * by the user, and then fills the color box with that pen color.
  164.  */
  165. {
  166.     SetAPen(ColorRPort, pen);
  167.     SetDrMd(ColorRPort, JAM1);
  168.     RectFill(ColorRPort, COLOR_BOX_LEFT, COLOR_BOX_TOP, 
  169.         COLOR_BOX_RIGHT, COLOR_BOX_BOTTOM);
  170. }
  171.  
  172.  
  173.  
  174. VOID DrawColorWindow()
  175. /* This routine fills in all the graphic details of the ColorWindow */
  176. {
  177.     SHORT col, row, colstart, colend, rowstart;
  178.     SHORT savepen;
  179.  
  180.     savepen = ColorRPort->FgPen;
  181.  
  182.     InitColorSizes(ColorRPort->BitMap->Depth);
  183.  
  184.     ColorRectFill(ColorRPort->FgPen);
  185. /*???    DrawBox(ColorRPort, 1, 1, COLORWINDOW_WIDTH - 2, COLORWINDOW_HEIGHT - 2);*/
  186.     DrawBox(ColorRPort, COLOR_BOX_LEFT - 2, COLOR_BOX_TOP - 2, 
  187.             COLOR_BOX_RIGHT + 2, COLOR_BOX_BOTTOM + 2);
  188.     DrawBox(ColorRPort, COLOR_BOX_LEFT - 2, COLOR_COLOR_TOP - 2, 
  189.             COLOR_BOX_LEFT + (8 * 15) + 1, COLOR_COLOR_TOP + (4 * 10) + 1);
  190.  
  191.     colstart = COLOR_BOX_LEFT;
  192.     colend = colstart + ColumnWidth - 1;
  193.     for (col = 0; col < ColumnCount; col++)
  194.         {
  195.         rowstart = COLOR_COLOR_TOP;
  196.         for (row = 0; row < RowCount; row++)
  197.             {
  198.             SetAPen(ColorRPort, (row * ColumnCount) + col);
  199.             RectFill(ColorRPort, colstart, rowstart, colend, 
  200.                     rowstart + RowHeight - 1);
  201.             rowstart += RowHeight;
  202.             }
  203.         colstart += ColumnWidth;
  204.         colend += ColumnWidth;
  205.         }
  206.  
  207.     SetAPen(ColorRPort, savepen);
  208. }
  209.  
  210.  
  211.  
  212.                                         
  213. struct Window *OpenColorWindow(screen, firstpen)
  214. struct Screen *screen;
  215. SHORT firstpen;
  216. {
  217.     SHORT i;
  218.  
  219.     if (ColorNewWindow.Screen = screen) ColorNewWindow.Type = CUSTOMSCREEN;
  220.     else ColorNewWindow.Type = WBENCHSCREEN;
  221.  
  222.     if ((ColorWindow = OpenWindow(&ColorNewWindow)) == 0) return(NULL);
  223.  
  224.     ColorVPort = &ColorWindow->WScreen->ViewPort;
  225.     ColorRPort = ColorWindow->RPort;
  226.  
  227.     for (i = 0; i < 32; i++)
  228.         SavePalette[i] = GetRGB4(ColorVPort->ColorMap, i);
  229.  
  230.     SetAPen(ColorRPort, firstpen);
  231.     ResetColorProps();
  232.     DrawColorWindow();
  233.  
  234.     ColorMode = NULL;
  235.  
  236.     return(ColorWindow);
  237. }
  238.  
  239.  
  240.  
  241.  
  242. VOID CloseColorWindow(accept)
  243. BOOL accept;
  244. {
  245.     if (ColorWindow == NULL) return;
  246.  
  247.     if (NOT accept) LoadRGB4(ColorVPort, &SavePalette[0], 32);
  248.  
  249.     CloseWindow(ColorWindow);
  250.     ColorWindow = NULL;
  251. }
  252.  
  253.  
  254.  
  255.  
  256. /* ======================================================================= */
  257. /* === These Routines Manage the User Interaction ======================== */
  258. /* ======================================================================= */
  259.  
  260. BOOL ColorGadgetGotten(gadget)
  261. struct Gadget *gadget;
  262. /* This routine manages the user's gadget selection.  If one of the 
  263.  * end gadgets, such as OK or CANCEL, was selected then this routine
  264.  * returns FALSE, else it returns TRUE.
  265.  */
  266. {
  267.     switch (gadget->GadgetID)
  268.         {
  269.         case COLOR_OK:
  270.             CloseColorWindow(TRUE);
  271.             return(FALSE);
  272.             break;
  273.         case COLOR_CANCEL:
  274.             CloseColorWindow(FALSE);
  275.             return(FALSE);
  276.             break;
  277.         case COLOR_COPY:
  278.             ColorMode = COPYCOLOR;
  279.             break;
  280.         case COLOR_RANGE:
  281.             ColorMode = RANGE_FIRST;
  282.             break;
  283.         case COLOR_HSL_RGB:
  284.             ResetColorProps();
  285.             break;
  286.         }
  287.     return(TRUE);
  288. }
  289.  
  290.  
  291.  
  292. VOID ColorRange(first, last)
  293. SHORT first, last;
  294. /* Create the color range from first to last */
  295. {
  296.     SHORT i;
  297.     SHORT whole, redfraction, greenfraction, bluefraction, divisor;
  298.     USHORT rgb;
  299.     SHORT firstred, firstgreen, firstblue;
  300.     SHORT lastred, lastgreen, lastblue;
  301.     SHORT workred, workgreen, workblue;
  302.  
  303.     /* If the pen numbers are out of order, swap */
  304.     if (first > last)
  305.         {
  306.         i = first;
  307.         first = last;
  308.         last = i;
  309.         }
  310.  
  311.     /* I need to see a spread of at least two, where there's at least one
  312.      * spot between the endpoints, else there's no work to do so I
  313.      * might as well just return now.
  314.      */
  315.     if (first >= last - 1) return;
  316.  
  317.     rgb = GetRGB4(ColorVPort->ColorMap, first);
  318.     firstred = (rgb >> 8) & 0xF;
  319.     firstgreen = (rgb >> 4) & 0xF;
  320.     firstblue = (rgb >> 0) & 0xF;
  321.  
  322.     rgb = GetRGB4(ColorVPort->ColorMap, last);
  323.     lastred = (rgb >> 8) & 0xF;
  324.     lastgreen = (rgb >> 4) & 0xF;
  325.     lastblue = (rgb >> 0) & 0xF;
  326.  
  327.  
  328.     divisor = last - first;
  329.  
  330.     /* Do all math as fixed-point fractions where the low 8 bits are 
  331.      * the fraction.  This greatly lessens the effect of rounding errors.
  332.      */
  333.     whole = (lastred - firstred) << 8;
  334.     redfraction = whole / divisor;
  335.  
  336.     whole = (lastgreen - firstgreen) << 8;
  337.     greenfraction = whole / divisor;
  338.  
  339.     whole = (lastblue - firstblue) << 8;
  340.     bluefraction = whole / divisor;
  341.  
  342.     for (i = first + 1; i < last; i++)
  343.         {
  344.         lastred = ((redfraction * (i - first)) + 0x0080) >> 8;
  345.         workred = firstred + lastred;
  346.         lastgreen = ((greenfraction * (i - first)) + 0x0080) >> 8;
  347.         workgreen = firstgreen + lastgreen;
  348.         lastblue = ((bluefraction * (i - first)) + 0x0080) >> 8;
  349.         workblue = firstblue + lastblue;
  350.         SetRGB4(ColorVPort, i, workred, workgreen, workblue);
  351.         }
  352. }
  353.  
  354.  
  355.  
  356.  
  357. VOID ColorWindowHit(x, y)
  358. SHORT x, y;
  359. /* The color boxes at the bottom-right of the ColorWindow are not gadgets.
  360.  * Instead, it's just graphics and this routine is used to detect whether
  361.  * the user has selected one of the color boxes.
  362.  */
  363. {
  364.     USHORT rgb, pen;
  365.  
  366.     /* Have we got a color specifier? */
  367.     if ( (x >= COLOR_BOX_LEFT) && (x <= COLOR_COLOR_RIGHT)
  368.             && (y >= COLOR_COLOR_TOP) && (y <= COLOR_COLOR_BOTTOM) )
  369.         {
  370.         /* Yes, it's one of the color boxes.  Set this pen number */
  371.         x = x - COLOR_BOX_LEFT;
  372.         x = x / ColumnWidth;
  373.         y = y - COLOR_COLOR_TOP;
  374.         y = y / RowHeight;
  375.         pen = (y * ColumnCount) + x;
  376.  
  377.         /* first, were we in COPY COLOR mode? */
  378.         if (ColorMode == COPYCOLOR)
  379.             {
  380.             /* ok, copy old color here first! */
  381.             rgb = GetRGB4(ColorVPort->ColorMap, ColorRPort->FgPen);
  382.             SetRGB4(ColorVPort, pen, rgb >> 8, rgb >> 4, rgb);
  383.             ColorMode = NULL;
  384.             }
  385.         else if (ColorMode == RANGE_FIRST)
  386.             {
  387.             ColorMode = RANGE_SECOND;
  388.             RangeFirst = pen;
  389.             }
  390.         else if (ColorMode == RANGE_SECOND)
  391.             {
  392.             ColorMode = NULL;
  393.             ColorRange(RangeFirst, pen);
  394.             }
  395.         ColorRectFill(pen);
  396.  
  397.         ResetColorProps();
  398.         }
  399. }
  400.  
  401.  
  402.  
  403. VOID SetPropValueGrunt(value, y)
  404. SHORT value, y;
  405. {
  406.     UBYTE text[16];
  407.  
  408.     if (value >= 0) sprintf(&text[0], "%ld ", value);
  409.     else
  410.         {
  411.         text[0] = ' ';
  412.         text[1] = ' ';
  413.         }
  414.  
  415.     Move(ColorRPort, COLOR_VALUE_X, y);
  416.     Text(ColorRPort, &text[0], 2);
  417. }
  418.  
  419.  
  420.  
  421. VOID SetPropValues(red, green, blue)
  422. SHORT red, green, blue;
  423. /* Sets the text to the right of the prop gadgets */
  424. {
  425.     SHORT savepen;
  426.  
  427.     savepen = ColorRPort->FgPen;
  428.  
  429.     SetAPen(ColorRPort, 1);
  430.     SetDrMd(ColorRPort, JAM2);
  431.  
  432.     SetPropValueGrunt(red, COLOR_VALUE_REDY);
  433.     SetPropValueGrunt(green, COLOR_VALUE_GREENY);
  434.     SetPropValueGrunt(blue, COLOR_VALUE_BLUEY);
  435.  
  436.     SetAPen(ColorRPort, savepen);
  437. }
  438.  
  439.  
  440.  
  441. VOID ModifyRGBColors()
  442. {
  443.     USHORT newred, newgreen, newblue;
  444.  
  445.     newred = ColorPropsInfos[0].HorizPot >> 12;
  446.     newgreen = ColorPropsInfos[1].HorizPot >> 12;
  447.     newblue = ColorPropsInfos[2].HorizPot >> 12;
  448.  
  449.     SetRGB4(ColorVPort, ColorRPort->FgPen, newred, newgreen, newblue);
  450.     SetPropValues(newred, newgreen, newblue);
  451. }
  452.  
  453.  
  454.  
  455.  
  456. VOID ModifyHSLColors()
  457. {
  458.     USHORT rgb;
  459.  
  460.     rgb = (USHORT)HSLToRGB(
  461.             ColorPropsInfos[0].HorizPot,
  462.             ColorPropsInfos[1].HorizPot,
  463.             ColorPropsInfos[2].HorizPot);
  464.  
  465.     SetRGB4(ColorVPort, ColorRPort->FgPen, rgb >> 8, rgb >> 4, rgb);
  466.     SetPropValues(-1, -1, -1);
  467. }
  468.  
  469.  
  470.  
  471.  
  472. VOID ModifyColors()
  473. /* This routine reacts to the user playing with one of the prop gadgets */
  474. {
  475.     if (ColorTemplateGadgets[COLOR_HSL_RGB].Flags & SELECTED)
  476.         ModifyHSLColors();
  477.     else
  478.         ModifyRGBColors();
  479. }
  480.  
  481.  
  482.  
  483. VOID SetRGBProps(rgb)
  484. USHORT rgb;
  485. {
  486.     USHORT red, green, blue;
  487.  
  488.     red = (rgb >> 8) & 0xF;
  489.     green = (rgb >> 4) & 0xF;
  490.     blue = (rgb >> 0) & 0xF;
  491.  
  492.     ColorPropsInfos[0].HorizPot
  493.             = (red << 12) | (red << 8) | (red << 4) | red;
  494.     ColorPropsInfos[1].HorizPot
  495.             = (green << 12) | (green << 8) | (green << 4) | green;
  496.     ColorPropsInfos[2].HorizPot
  497.             = (blue << 12) | (blue << 8) | (blue << 4) | blue;
  498.  
  499.     SetPropValues(red, green, blue);
  500. }
  501.  
  502.  
  503.  
  504. VOID SetHSLProps(rgb)
  505. USHORT rgb;
  506. {
  507.     RGBToHSL(rgb,
  508.             &ColorPropsInfos[0].HorizPot,
  509.             &ColorPropsInfos[1].HorizPot,
  510.             &ColorPropsInfos[2].HorizPot);
  511.  
  512.     SetPropValues(-1, -1, -1);
  513. }
  514.  
  515.  
  516.  
  517. VOID ResetColorProps()
  518. /* This routine resets the proportional gadgets according to the current
  519.  * pen number and the interaction technique
  520.  */
  521. {
  522.     SHORT bluepos;
  523.     USHORT rgb;
  524.  
  525.     rgb = GetRGB4(ColorVPort->ColorMap, ColorRPort->FgPen);
  526.  
  527.     bluepos = RemoveGList(ColorWindow, &ColorTemplateGadgets[COLOR_BLUE], 3);
  528.  
  529.     if (ColorTemplateGadgets[COLOR_HSL_RGB].Flags & SELECTED)
  530.         SetHSLProps(rgb);
  531.     else SetRGBProps(rgb);
  532.  
  533.     AddGList(ColorWindow, &ColorTemplateGadgets[COLOR_BLUE], bluepos, 3, 0);
  534.     RefreshGList(&ColorTemplateGadgets[COLOR_BLUE], ColorWindow, NULL, 3);
  535. }
  536.  
  537.  
  538.  
  539.  
  540.  
  541. /* ======================================================================= */
  542. /* === And finally, the Main Entry Point ================================= */
  543. /* ======================================================================= */
  544.  
  545.  
  546. /* *** DoColorWindow() ******************************************************
  547.  * 
  548.  * NAME
  549.  *     DoColorWindow  --  Allows the user to change a screen's colors
  550.  * 
  551.  * 
  552.  * SYNOPSIS
  553.  *     BOOL DoColorWindow(Screen, Left, Top, FirstPen, UseRGB);
  554.  * 
  555.  * 
  556.  * FUNCTION
  557.  *     This routine creates a window, called the ColorWindow, which has 
  558.  *     gadgets that allow the user to change the colors of any screen.  
  559.  *     After opening the ColorWindow, this routine interacts with the 
  560.  *     user until the user is satisfied with the current colors, at which 
  561.  *     time the window is closed and control is returned to you.  
  562.  * 
  563.  *     The ColorWindow will open in the specified Screen.  The Screen 
  564.  *     argument can be equal to NULL; if it is, the ColorWindow will be 
  565.  *     opened in the Workbench screen.  The ColorWindow automatically 
  566.  *     adapts itself to any screen.  
  567.  * 
  568.  *     With the Top and Left arguments you specify the position of the 
  569.  *     ColorWindow's top-left corner.  Note that no position-error 
  570.  *     checking is done, so you must take care to not place the window 
  571.  *     outside of the bounds of your screen.  Currently, the Left argument 
  572.  *     can range from 0 to 88 on low-resolution screens, and 0 to 408 
  573.  *     on high-resolution screens.  The Top argument can range from 
  574.  *     0 to 109 on a 200-line screen, and 0 to 309 on an interlaced screen.  
  575.  *     These figures don't include overscan, which most programmers 
  576.  *     don't use.  The width and height of the ColorWindow are defined 
  577.  *     by the constants COLORWINDOW_WIDTH and COLORWINDOW_HEIGHT in the 
  578.  *     color.h file.  
  579.  * 
  580.  *     The FirstPen argument is used to initialize the color that's 
  581.  *     displayed when the ColorWindow is first created.  
  582.  * 
  583.  *     The ColorWindow is capable of allowing the user to modify the 
  584.  *     colors using either an RGB or an HSL technique.  The RGB technique 
  585.  *     involves three proportional gadgets, one for each of Red, Green 
  586.  *     and Blue.  By adjusting one of these gadgets, the user adjusts 
  587.  *     the amount of the associated color component in the final color.  
  588.  *     Some people feel that this is the most intuitive way to change 
  589.  *     colors on the Amiga, as this is how colors are represented 
  590.  *     internally by the Amiga.  The other technique, HSL, allows the 
  591.  *     user to adjust the Hue, Saturation and Luminance of the final color.  
  592.  *     Some people feel that *this* is the most intuitive way for users 
  593.  *     to change color, because it's based on color theory and because 
  594.  *     these are the types of controls that people used on their 
  595.  *     color televisions in the old days.  
  596.  * 
  597.  *     You decide which mode is first used when the ColorWindow is created 
  598.  *     by setting the UseRGB argument to TRUE or FALSE.  If TRUE, 
  599.  *     the RGB technique will be used.  If FALSE, HSL is used.  
  600.  * 
  601.  *     But regardless of which technique you specify, the user can switch 
  602.  *     to using the other technique by clicking on the RGB / HSL characters 
  603.  *     that appear to the left of the proportional gadgets.  
  604.  * 
  605.  *     On return from this function, this routine returns TRUE if all 
  606.  *     went well.  If anything went wrong (usually out of memory) and 
  607.  *     the ColorWindow was never created, this routine returns FALSE.  
  608.  * 
  609.  *     NOTE:  This routine is not re-entrant.  What this means 
  610.  *     is that if you have created a program that has more than one task,
  611.  *     this routine cannot be called by more than one task at a time.
  612.  *     This was done for the sake of memory efficiency.
  613.  *     This restriction is not a problem for the grand majority of programs.
  614.  *     But if you have some application that would require calling this 
  615.  *     routine asynchronously from multiple tasks, you'll have to 
  616.  *     implement some quick semaphore arrangement to avoid collisions.
  617.  *     No big deal, actually.  See Exec semaphores for everything you need.
  618.  * 
  619.  * 
  620.  * INPUTS
  621.  *     Screen = address of the screen in which the ColorWindow will open.
  622.  *         Can be NULL; if so, the ColorWindow will open in the Workbench
  623.  *     Left = position of the left edge when the ColorWindow opens
  624.  *     Top = position of the top edge when the ColorWindow opens
  625.  *     FirstPen = pen number of the color displayed when the ColorWindow
  626.  *         first opens
  627.  *     UseRGB = TRUE if you want the RGB technique displayed first, 
  628.  *         FALSE if you want the HSL technqiue.  See the discussion above
  629.  * 
  630.  * 
  631.  * RESULT
  632.  *     Returns TRUE if all went well.  If the window couldn't be opened for
  633.  *     any reason, returns FALSE.
  634.  * 
  635.  * 
  636.  */
  637. BOOL DoColorWindow(screen, left, top, firstpen, usergb)
  638. struct Screen *screen;
  639. SHORT left, top, firstpen;
  640. BOOL usergb;
  641. {
  642.     struct IntuiMessage *message;
  643.     ULONG class;
  644.     struct Gadget *gadget;
  645.     BOOL mousemoved;
  646.     SHORT x, y, code, i;
  647.     struct Remember *key;
  648.     UWORD *ptr;
  649.     BOOL retvalue;
  650.  
  651.     key = NULL;
  652.     retvalue = FALSE;
  653.  
  654.     if (ColorWindow) goto DONE;
  655.  
  656.     ColorNewWindow.LeftEdge = left;
  657.     ColorNewWindow.TopEdge = top;
  658.  
  659.     if (usergb)
  660.         ColorTemplateGadgets[COLOR_HSL_RGB].Flags &= ~SELECTED;
  661.     else
  662.         ColorTemplateGadgets[COLOR_HSL_RGB].Flags |= SELECTED;
  663.  
  664.     if ((ptr = (UWORD *)AllocRemember(&key, RGBHSL_SIZE * 2, MEMF_CHIP))
  665.             == NULL)
  666.         goto DONE;
  667.     ColorRGBImage.ImageData = ptr;
  668.     for (i = 0; i < RGBHSL_SIZE; i++)
  669.         *ptr++ = RGBData[i];
  670.     if ((ptr = (UWORD *)AllocRemember(&key, RGBHSL_SIZE * 2, MEMF_CHIP))
  671.             == NULL)
  672.         goto DONE;
  673.     ColorHSLImage.ImageData = ptr;
  674.     for (i = 0; i < RGBHSL_SIZE; i++)
  675.         *ptr++ = HSLData[i];
  676.  
  677.     if (NOT OpenColorWindow(screen, firstpen & 0x3F)) goto DONE;
  678.  
  679.     retvalue = TRUE;
  680.  
  681.     FOREVER
  682.         {
  683.         Wait(1 << ColorWindow->UserPort->mp_SigBit);
  684.  
  685.         mousemoved = FALSE;
  686.         while (message = GetMsg(ColorWindow->UserPort))
  687.             {
  688.             class = message->Class;
  689.             code = message->Code;
  690.             gadget = (struct Gadget *)(message->IAddress);
  691.             x = message->MouseX;
  692.             y = message->MouseY;
  693.             ReplyMsg(message);
  694.  
  695.             switch (class)
  696.                 {
  697.                 case GADGETDOWN:
  698.                 case GADGETUP:
  699.                     if (ColorGadgetGotten(gadget) == FALSE)
  700.                         goto DONE;
  701.                     break;
  702.                 case MOUSEMOVE:
  703.                     mousemoved = TRUE;
  704.                     break;
  705.                 case MOUSEBUTTONS:
  706.                     if (code == SELECTDOWN) ColorWindowHit(x, y);
  707.                     break;
  708.                 }
  709.             }
  710.         if (mousemoved) ModifyColors();
  711.         }
  712.  
  713. DONE:
  714.     FreeRemember(&key, TRUE);
  715.     return(retvalue);
  716. }
  717.  
  718.  
  719.